package org.nobject.common.http;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;

import org.nobject.common.apps.Callback;
import org.nobject.common.js.JSONUtils;
import org.nobject.common.lang.IOUtils;
import org.nobject.common.lang.StringUtils;
import org.nobject.common.net.URLUtils;

/**
 * Http工具
 * 
 * EXP:
 * 
 * 	String url="http://127.0.0.1:8081/ppm_rv/mmvc/jsonrpc/call";
 * 	String content="rpc=coreRPC&method=login&params=%5B%27admin%27%2C%20%271232456%27%2C%20%27%27%5D";
 * 	HttpUtils hu=new HttpUtils();
 * 	hu.postHTML(url,content,"UTF-8");
 * 	for (HttpCookie hc:hu.cookies.values()) {
 * 		System.out.print(hc.key+":"+hc.value);
 * 	}
 * 	System.out.println(hu.getReponseText());
 * 
 * @author bianrongjun
 * @version 1.0
 */
public class HttpUtils {
	
	/** cookies */
	public Map<String,HttpCookie> cookies;
	
	/** responseBytes */
	private byte[] responseBytes;
	
	/** responseCharset */
	private String responseCharset="UTF-8";
	
	/**
	 * 构造函数 
	 */
	public HttpUtils(){
		cookies=new HashMap();
	}
	
	/** 
	 * 格式化URI
	 * EXP:
	 * 	formartUri("/ppm_rv//mmvc/aa")
	 * @param uri
	 */
	public static String formatUri(String uri){
		while(uri.indexOf("//")>=0){
			uri=uri.replaceAll("//","/");
		}
		return uri;
	}
	
	/** 
	 * 同步Cookie
	 * @param conn 连接
	 */
	public void syncCookie(HttpURLConnection conn){
		 //设置Cookie
        StringBuffer sb=new StringBuffer();
        for (Iterator iterator = this.cookies.values().iterator(); iterator.hasNext();) {
			HttpCookie hc =(HttpCookie)iterator.next();
			sb.append(hc.key+"="+hc.value);
			if(iterator.hasNext()){
				sb.append(";");
			}
		}
        if(sb.length()>0) conn.setRequestProperty("Cookie", sb.toString());
	}
	
	/** 
	 * 上传文件
	 * @param url
	 * @param file
	 * @param charset
	 * @throws Exception
	 */
	public String uploadFile(String url,InputStream is,String fileName,Callback callback) throws Exception{
		String end ="\r\n";
		String twoHyphens ="--";
		String boundary ="*****";
		
		//发送
		HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
		conn.setRequestMethod("POST");
		//conn.setConnectTimeout(connectTimeout);
		//conn.setReadTimeout(readTimeout);
		
		conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setUseCaches(false);
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Charset", "UTF-8");
        conn.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
        conn.setInstanceFollowRedirects(true);
        
     	//设置Cookie
        syncCookie(conn);
        
		DataOutputStream ds =new DataOutputStream(conn.getOutputStream());
		
		//Head
		ds.writeBytes(twoHyphens + boundary + end);
		ds.writeBytes("Content-Disposition: form-data; "+"name=\"file1\";filename=\""+fileName +"\""+ end);
		ds.writeBytes(end);
		
		//Body
		int bufferSize =1024;
		byte[] buffer =new byte[bufferSize];
		int length =-1;
		int alllength=0;
		while((length = is.read(buffer)) !=-1){
			alllength+=length;
			//回调
			if(callback!=null) callback.execute(new Object[]{alllength});
			ds.write(buffer, 0, length);
		}
		ds.writeBytes(end);
		ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
		/* close streams */
		is.close();
		ds.flush();
		

		//读取相应
		is = conn.getInputStream();
		this.responseBytes=IOUtils.getBytes(is);
		ds.close();
		return new String(this.responseBytes);
	}
	
	/** 
	 * POST方式获取HTML
	 * @param url 地址
	 * @param content 内容
	 * @param charset 字符集
	 */
	public void postHTML(String url,String content,String charset) throws Exception{
		postHTML(url, content, charset, 6 * 1000, 6 * 1000);
	}
	
	/** 
	 * postHTML
	 * @param url
	 * @param content
	 * @param charset
	 * @param connectTimeout
	 * @param readTimeout
	 * @throws Exception
	 */
	public void postHTML(String url,String content,String charset,int connectTimeout,int readTimeout) throws Exception{
		String contentType="application/x-www-form-urlencoded; charset="+charset;
		postHTML(url, content, charset, connectTimeout,readTimeout,contentType);
	}
	
	public static void main(String[] args) throws Exception{
		String url="http://116.255.254.108:80/cellindex.gl?did=364555BBC5494E869EDDACC6E1539BCF";
		String content="";
		HttpUtils httpUtils=new HttpUtils();
		httpUtils.postHTML(url,content,"GBK");
		System.out.println(new String(httpUtils.getReponseBytes(),"GBK"));
	}
	
	/** 
	 * POST方式获取HTML
	 * @param url 地址
	 * @param content 内容
	 * @param charset 字符集
	 * @param timeout 超时时间
	 * @param contentType 内容类型
	 */
	public void postHTML(String url,String content,String charset,int connectTimeout,int readTimeout,String contentType) throws Exception{
		//发送
		HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
		conn.setRequestMethod	("POST");
		conn.setConnectTimeout	(connectTimeout);
		conn.setReadTimeout		(readTimeout);
		conn.setDoOutput		(true);
        conn.setDoInput			(true);
        conn.setUseCaches		(false);
        conn.setInstanceFollowRedirects(true);
        
        //设置Cookie
        syncCookie(conn);
        
        //编码
        byte [] datas=content!=null?content.getBytes(charset):new byte[]{};
        if(!StringUtils.isEmpty(contentType)) conn.addRequestProperty("Content-Type", contentType);
        conn.addRequestProperty("Content-Length",String.valueOf(datas.length));
        
	    conn.connect();
    	OutputStream outStream = conn.getOutputStream();   
	    outStream.write(datas);   
	    outStream.flush();   
	    outStream.close();
	    
		if (conn.getResponseCode() == 200) {
			InputStream inStream = null;
			String contentEncoding = conn.getContentEncoding();
			
			String cookieVal = null;
			String key = null;
			//读取Cookie
			String domain=StringUtils.removeStart(url, "http://");
			domain=domain.substring(0, domain.indexOf("/"));
			for (int i = 1; (key = conn.getHeaderFieldKey(i)) != null; i++) {
				if (key.equalsIgnoreCase("set-cookie")) {
					cookieVal = conn.getHeaderField(i);
					cookieVal = cookieVal.substring(0, cookieVal.indexOf(";"));
					String[] cs=cookieVal.split("=");
					HttpCookie ch=new HttpCookie(cs[0],cs[1],null,domain,null);
					this.cookies.put(ch.key,ch);
				}
			}
			
			//解压缩
			if ((null != contentEncoding)) {
				if (-1 != contentEncoding.indexOf("gzip"))
					inStream = new GZIPInputStream(conn.getInputStream());
				else if (-1 != contentEncoding.indexOf("deflate"))
					inStream = new InflaterInputStream(conn.getInputStream());
				else
					inStream = conn.getInputStream();
			} else {
				inStream = conn.getInputStream();
			}
			
			//数据流
			ByteArrayOutputStream bOutPutStream = new ByteArrayOutputStream();
			byte[] bb = new byte[1024];
			int len = -1;
			while ((len = inStream.read(bb)) != -1){
				bOutPutStream.write(bb, 0, len);
			}
			bOutPutStream.close();
			inStream.close();
			
			this.responseBytes= bOutPutStream.toByteArray();
		} else {
			System.out.println("responseCode:"+conn.getResponseCode());
		}
	}
	
	/** 
	 * 获取输入流
	 * @param url
	 * @param connectTimeout
	 * @param readTimeout
	 */
	public InputStream getInputStream(String url,int connectTimeout,int readTimeout) throws Exception{
		URL url2 = new URL(url); 
		HttpURLConnection conn = (HttpURLConnection)url2.openConnection(); 
		conn.setRequestMethod		("GET"); 
		conn.setConnectTimeout		(connectTimeout);
		conn.setReadTimeout			(readTimeout);
		syncCookie(conn);
		return conn.getInputStream(); 
	}
	
	public static void main2(String[] args) throws Exception{
		
		String url="http://127.0.0.1:8081/mmvc/jsonrpc/call";
		String content="rpc=coreRPC&method=login&params="+URLUtils.encode(JSONUtils.toString(new Object[]{"admin","123456",new HashMap()}));
		HttpUtils httpUtils=new HttpUtils();
		httpUtils.postHTML(url,content,"UTF-8");
		for (HttpCookie hc:httpUtils.cookies.values()) {
			System.out.print(hc.key+":"+hc.value);
		}
		System.out.println(httpUtils.getReponseText());
		
		InputStream is=IOUtils.getInputStreamByFilepath("c:/a.txt");
		System.out.println(httpUtils.uploadFile("http://192.168.200.225:8081/mmvc/upload/?uploadPolicy=basDfileUP", is,"a.txt",null));;
		System.out.println(httpUtils.getReponseText());
	}
	
	public static void main3(String[] args) throws Exception{
		
		
		String url="http://116.255.207.120:9989/eos_han/mmvc/jsonrpc/call";
		String content="rpc=coreRPC&method=login&params="+URLUtils.encode(JSONUtils.toString(new Object[]{"admin","123456",new HashMap()}));
		HttpUtils httpUtils=new HttpUtils();
		httpUtils.postHTML(url,content,"UTF-8");
		for (HttpCookie hc:httpUtils.cookies.values()) {
			System.out.print(hc.key+":"+hc.value);
		}
		System.out.println(httpUtils.getReponseText());
		
		content="rpc=basOrgRPC&method=queryL&params="+URLUtils.encode(JSONUtils.toString(new Object[]{"安大"}));
		httpUtils.postHTML(url,content,"UTF-8");
		System.out.println(httpUtils.getReponseText());
//		String url="http://117.158.16.101:8082/MOSDC/zsxy_call";
//		String content="rpc=zsxyService&method=login&params="+JSONUtils.toString(new Object[]{"admin","1",new HashMap()});
//		HttpUtils httpUtils=new HttpUtils();
//		httpUtils.postHTML(url,content,"UTF-8");
//		for (HttpCookie hc:httpUtils.cookies.values()) {
//			System.out.print(hc.key+":"+hc.value);
//		}
//		System.out.println(httpUtils.getReponseText());
		
//		for (HttpCookie hc:httpUtils.cookies.values()) {
//			System.out.print(hc.key+":"+hc.value);
//		}
//		System.out.println(httpUtils.getReponseText());
//		url="http://117.158.16.101:8082/MOSDC/uploadFile/zsxy/news/exp_news_3.jpg";
//		InputStream is=httpUtils.getInputStream(url,  6 * 1000, 6 * 1000);
//		byte[] bs=IOUtils.getBytes(is);
//		FileUtils.makeFile("C:/exp_news_3.jpg",bs);
//		System.out.println(new String(bs));
	}
	
	/** 
	 * 获取响应字节
	 */
	public byte[] getReponseBytes(){
		return this.responseBytes;
	}
	
	/** 
	 * 获取响应文本
	 */
	public String getReponseText(){
		try {
			return new String(this.responseBytes,this.responseCharset);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	///////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////
	
	/** 
	 * 获取并保存资源
	 * @param url
	 * @param path
	 * @throws Exception
	 */
	public static void getAndSaveResource(String url,String path)throws Exception{
		HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
		if (conn.getResponseCode() != HttpURLConnection.HTTP_OK)  throw new Exception("未获取成功");
		InputStream inStream = null;
		String contentEncoding = conn.getContentEncoding();
		if ((null != contentEncoding)) {
			if (-1 != contentEncoding.indexOf("gzip")) inStream = new GZIPInputStream(conn.getInputStream());
			else if (-1 != contentEncoding.indexOf("deflate")) inStream = new InflaterInputStream(conn.getInputStream());
			else inStream = conn.getInputStream();
		} else  inStream = conn.getInputStream();
		//FileUtils.makeFile(path, null);
		File f=new File(path);
		if(!f.getParentFile().exists()) f.getParentFile().mkdirs();
		FileOutputStream fileoutPutStream = new FileOutputStream(f);
		byte[] bb = new byte[1024];
		int len = -1;
		while ((len = inStream.read(bb)) != -1) fileoutPutStream.write(bb, 0, len);
		fileoutPutStream.close();
		inStream.close();
		return ;
	}
	
	/** 
	 * getResourceBytes
	 * @param url
	 */
	public static byte[] getResourceBytes(String url) throws Exception {
		HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
		if (conn.getResponseCode() != HttpURLConnection.HTTP_OK)  throw new Exception("未获取成功");
		InputStream inStream = null;
		String contentEncoding = conn.getContentEncoding();
		if ((null != contentEncoding)) {
			if (-1 != contentEncoding.indexOf("gzip")) inStream = new GZIPInputStream(conn.getInputStream());
			else if (-1 != contentEncoding.indexOf("deflate")) inStream = new InflaterInputStream(conn.getInputStream());
			else inStream = conn.getInputStream();
		} else  inStream = conn.getInputStream();
		ByteArrayOutputStream bOutPutStream = new ByteArrayOutputStream();
		byte[] bb = new byte[1024];
		int len = -1;
		while ((len = inStream.read(bb)) != -1){
			bOutPutStream.write(bb, 0, len);
		}
		bOutPutStream.close();
		inStream.close();
		return bOutPutStream.toByteArray();
	}

	/**
	 * GET方式获取网页内容
	 * @param url 地址
	 * @param charset 字符集
	 */
	public static String getHTML(String url, String charset) throws Exception {
		HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
		conn.setRequestMethod("GET");
		conn.setConnectTimeout(6 * 1000);
		if (conn.getResponseCode() == 200) {
			InputStream inStream = null;
			String contentEncoding = conn.getContentEncoding();
			if ((null != contentEncoding)) {
				if (-1 != contentEncoding.indexOf("gzip"))
					inStream = new GZIPInputStream(conn.getInputStream());
				else if (-1 != contentEncoding.indexOf("deflate"))
					inStream = new InflaterInputStream(conn.getInputStream());
				else
					inStream = conn.getInputStream();
			} else {
				inStream = conn.getInputStream();
			}
			ByteArrayOutputStream bOutPutStream = new ByteArrayOutputStream();
			byte[] bb = new byte[1024];
			int len = -1;
			while ((len = inStream.read(bb)) != -1)
				bOutPutStream.write(bb, 0, len);
			bOutPutStream.close();
			inStream.close();
			byte[] data = bOutPutStream.toByteArray();
			return new String(data, charset);
		} else {
			return null;
		}
	}
	
	/** 
	 * getParameterMap
	 * @param parameterMap
	 */
	public static Map getParameterMap(Map parameterMap) {
		// 参数Map
		Map properties = parameterMap;
		// 返回值Map
		Map returnMap = new HashMap();
		Iterator entries = properties.entrySet().iterator();
		Map.Entry entry;
		String name = "";
		String value = "";
		while (entries.hasNext()) {
		    entry = (Map.Entry) entries.next();
		    name = (String) entry.getKey();
		    Object valueObj = entry.getValue();
		    if(null == valueObj){
		        value = "";
		}else if(valueObj instanceof String[]){
		    String[] values = (String[])valueObj;
		    for(int i=0;i<values.length;i++){
		        value = values[i] + ",";
		        }
		        value = value.substring(0, value.length()-1);
		    }else{
		        value = valueObj.toString();
		    }
		    returnMap.put(name, value);
		}
		return returnMap;
	}

}
